#include <iostream>
#include <sys/socket.h>
#include <netdb.h>
#include <cstdio>
#include <unistd.h>
#include <cstdlib>
#include <arpa/inet.h>
#include <cstring>

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        std::cout << "Usage: ./server port" << std::endl;
        return -1;
    }

    // 1、创建服务端的socket
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd == -1)
    {
        std::cout << "socket err!" << std::endl;
        return -1;
    }

    // 2、把服务端用于通信的ip和端口绑定到socket上
    struct sockaddr_in serveraddr;   // 用于存放服务端ip和端口的数据结构
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;   // 指定ipv4
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);   // 服务器端任意网卡的ip都可用于通讯，服务器可能在不同网段拥有多个ip
    serveraddr.sin_port = htons(std::atoi(argv[1]));   // 指定端口
    // 绑定服务端的ip和端口
    int bindId = bind(listenfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
    if(bindId != 0)
    {
        std::cout << "bind err" << std::endl;
        return -1;
    }


    // 3、把socket设置为监听状态
    auto listenId = listen(listenfd, 5);
    if (listenId != 0)
    {
        std::cout << "listen err" << std::endl;
        return -1;
    } 

    // 4、受理客户的连接请求，如果没有客户连接，则accept函数一直阻塞
    int clientfd = accept(listenfd, 0, 0);
    if (clientfd == -1)
    {
        std::cout << "accept err" << std::endl;
        close(listenfd);
        return -1;
    }

    std::cout << "客户已连接" << std::endl;

    // 5、与客户端通信，接受客户端发过来的报文后，回复ok
    char buffer[1024];
    while (true)
    {
        int retIndex;
        memset(buffer, 0, sizeof(buffer));
        // 接受客户端的请求报文，如果客户端没有发送请求报文，recv()函数将阻塞等待
        // 如果客户端已断开连接，recv()函数将返回0

        retIndex = recv(clientfd, buffer, sizeof(buffer), 0);
        if (retIndex <= 0)
        {
            std::cout << "retIndex=" << retIndex << std::endl;
            break;
        }
        std::cout << "接收:" << buffer << std::endl;

        strcpy(buffer, "ok"); // 生成回应报文
        // 向客户发送回应报文
        retIndex = send(clientfd, buffer, strlen(buffer), 0);
        if (retIndex <= 0)
        {
            std::cout << "send error" << std::endl;
            break;
        }
        std::cout << "发送:" << buffer << std::endl;
        
    }
    
    // 6、关闭socket，释放资源
    close(clientfd);  // 关闭客户端连上来的socket
    close(listenfd);  // 关闭监听的socket
    
    return 0;
}

